/*
 * Wechat Bluetooth API
 */
var sendCommandCount = 0;
var wxDeviceData = "";
var wxDeviceDataIndex = -1;
var BleManage = function(){};
//错误信息
var errInfo = {
    STAUS_BLUETOOTH_OFF : "请开启手机蓝牙模块",
    STAUS_BLUETOOTH_UNAUTHORIZED : "您还没有授权微信使用蓝牙功能",
    MISS_BLUETOOTH_DEVICE : "没有连接上设备，请重试",
};

BleManage.prototype = {
    
    //初始化微信配置
    bleInit_callback_: function(opts,func) {
        this.opts = opts;

        wx.config({
            beta : true, //坑：这个很重要，必须配置这个为true,才能调用微信的硬件API  
            debug : true, //是否开启调试模式，会自动弹一些消息框显示微信返回的数据  
            appId : opts.appId, 
            timestamp : opts.timestamp,
            nonceStr : opts.nonceStr,
            signature : opts.signature,
            jsApiList : [ //需要调用的接口，都得在这里面写一遍      
            "openWXDeviceLib",//初始化设备库（只支持蓝牙设备）      
            "closeWXDeviceLib",//关闭设备库（只支持蓝牙设备）      
            "getWXDeviceInfos",//获取设备信息（获取当前用户已绑定的蓝牙设备列表）      
            "sendDataToWXDevice",//发送数据给设备      
            "startScanWXDevice",//扫描设备（获取周围所有的设备列表，无论绑定还是未被绑定的设备都会扫描到）      
            "stopScanWXDevice",//停止扫描设备      
            "connectWXDevice",//连接设备      
            "disconnectWXDevice",//断开设备连接      
            "getWXDeviceTicket",//获取操作凭证      
            //下面是监听事件：
            "onWXDeviceBindStateChange",//微信客户端设备绑定状态被改变时触发此事件      
            "onWXDeviceStateChange",//监听连接状态，可以监听连接中、连接上、连接断开      
            "onReceiveDataFromWXDevice",//接收到来自设备的数据时触发      
            "onScanWXDeviceResult",//扫描到某个设备时触发      
            "onWXDeviceBluetoothStateChange",//手机蓝牙打开或关闭时触发      
            ]  
        });
        wx.ready(function() {
            //初始化设备  
            wx.invoke('openWXDeviceLib', {}, function(res) {
                $("#initBle").append("<p>初始化设备库：" + res.err_msg + "</p>");
                if (res.bluetoothState == "on") {
                    if (res.err_msg == "openWXDeviceLib:ok") {
                        //初始化完成，执行回调方法
                        func();
                        //初始化完成，请求设备状态
                        //bleInit_getDev_Info();
                    }
                }else if (res.bluetoothState == "off") {
                    alert_LHX({
                        hasBtn: 1,
                        msg: errInfo.STAUS_BLUETOOTH_OFF
                    });
                    //alert(errInfo.STAUS_BLUETOOTH_OFF);
                }else if (res.bluetoothState == "unauthorized") {
                    alert_LHX({
                        hasBtn: 1,
                        msg: errInfo.STAUS_BLUETOOTH_UNAUTHORIZED
                    });
                    //(errInfo.STAUS_BLUETOOTH_UNAUTHORIZED);
                }
            });

            wx.on('onScanWXDeviceResult', function(res) {
                //delog("扫描结果："+JSON.stringify(res));
                var ret_ = res.devices;
                for (var i = 0; i < ret_.length; i++) {
                    var macid = JSON.stringify(res.devices[i].deviceId)  
                            .replace(/\"/g, "");
                    //给扫描到的设备添加点击事件  
                    $("#initBle").append("<button onclick=\"bindBle('" + macid + "')\">扫描到设备：" + macid + "</button>");
                }
            });

            //手机蓝牙状态改变时触发 （这是监听事件的调用方法，注意，监听事件都没有参数）      
            wx.on('onWXDeviceBluetoothStateChange', function(res) {
                //把res输出来看吧      
                $("#initBle").append("<p>蓝牙状态变更：" + JSON.stringify(res) + "</p>");
            });
            //设备绑定状态改变事件（解绑成功，绑定成功的瞬间，会触发）      
            wx.on('onWXDeviceBindStateChange', function(res) {
                $("#initBle").append("<p>绑定状态变更：" + JSON.stringify(res) + "</p>");
            });
            //设备连接状态改变      
            wx.on('onWXDeviceStateChange', function(res) {
                //有3个状态：connecting连接中,connected已连接,unconnected未连接      
                //每当手机和设备之间的状态改变的瞬间，会触发一次
                if (res.state == "connected") {
                    $("#initBle").append("<p>设备连接成功" + res.state + "</p>");
                    //设备连接成功
                    this.bleInit_readCardReady();
                }
            });
            //接收到设备传来的数据      
            wx.on('onReceiveDataFromWXDevice', function(res) {
                var obj = eval("(" + JSON.stringify(res) + ")");
                var data = Bytes2Str16(Str102Bytes(base64decode(obj.base64Data))).toUpperCase();
                $("#initBle").append("<p>收到设备数据：" + data + "</p>");
            });
            wx.error(function(res) {
                delog("wx.error错误：" + JSON.stringify(res));
                //如果初始化出错了会调用此方法，没什么特别要注意的      
            });

        });
    },
    //搜索蓝牙    
    bleInit_Scan : function() {
        wx.invoke('startScanWXDevice', { 'btVersion':'ble' }, function(res) {
            $("#initBle").append("<p>开始扫描设备ble：" + res.err_msg + "</p>");
        });
    },
    //停止搜索蓝牙    
    bleInit_stopScan : function() {
        wx.invoke('stopScanWXDevice', {}, function(res) {
            $("#initBle").append("<p>停止扫描设备：" + res.err_msg + "</p>");
            //alert(res.err_msg);    
        });
    },
    //连接设备
    bleInit_Connect_Dev : function(deviceId){
        wx.invoke('connectWXDevice', { 'deviceId': deviceId }, function (res) {
            if(res.err_msg == "connectWXDevice:ok"){
                bleInit_getDev_Info();
            }else{
                alert_LHX({
                    hasBtn: 1,
                    msg: errInfo.MISS_BLUETOOTH_DEVICE
                });

            }
        });
    },
    //绑定设备  
    bleInit_Bind_Dev : function(str) {  
        //alert("绑定需要后台获取jsTicket进行设备绑定");
    },
    //获取设备信息    
    bleInit_getDev_Info : function() {
        // 如果10秒内没有连接上蓝牙设备
        timeoutVar = setTimeout(function() {
           // alert(errInfo.MISS_BLUETOOTH_DEVICE);
            alert_LHX({
                hasBtn: 1,
                msg: errInfo.MISS_BLUETOOTH_DEVICE
            });
            //stopOneConnectClick();
        }, 10000);
        wx.invoke('getWXDeviceInfos', {}, function(res) {
            if (res.deviceInfos.length != 0) {
                for(var i = 0;i < res.deviceInfos.length;i++) {
                    if (res.deviceInfos[i].deviceId == opts.deviceId) {
                        state = res.deviceInfos[i].state;
                        $("#deviceState").html(state);
                        $("#initBle").append("<p>设备连接状态：" + state + "</p>");
                        if (state == "connected") {
                            //设备连接成功
                            bleInit_readCardReady();
                        } else {
                            //设备没有连接上
                            bleInit_Connect_Dev(opts.deviceId);
                        }
                        break;
                    }
                }
            }
        });
    },

    //发送数据    
    bleInit_sendData_Test : function() {
        //测试指令：进入卡片1001目录
        var test = "33800fc2010b008009010700a400000210017f";
        delog("发送指令"+test);
        //base64加密
        test = base64.encode(test);

        wx.invoke('sendDataToWXDevice',
        {
            'deviceId' : opts.deviceId,
            'base64Data' : test
        }, function(res) {

            delog(JSON.stringify(res))  
        });
    },
    bleInit_sendData : function(array, index) {
        if (index < array.length && array[index] != null) {
            delog("send=" + base64encode(bytes2Str10(Str162Bytes(array[index]))));

            wx.invoke('sendDataToWXDevice', {
                'deviceId': opts.deviceId,
                'base64Data': base64encode(bytes2Str10(Str162Bytes(array[index])))
            }, function (argv) {
                //var obj = eval("(" + JSON.stringify(argv) + ")");
                delog(JSON.stringify(argv));
                if (argv.err_msg.indexOf("ok") >= 0) {
                    if (index < array.length) {
                        this.bleInit_sendData(array, index + 1);
                    }
                } else {
                    delog("send data error");
                }
            });
        }
    },

    bleInit_readCardReady : function() {
        this._sendDataToWXDevice("AE01C0", function (data) {
            var deviceId = bytes2Str10(Str162Bytes(data.substr(8, data.length)));
            if (opts.deviceId != deviceId) {
                delog("deviceNo is not binded.");
                return false;
            }
            // 获取设备电量
            this._sendDataToWXDevice("AE01C2", function (data) {
                var temp = data.substring(8, data.length);
                var power = Str162Bytes(temp)[0];
                delog("设备电量为："+power);
                if (power < 20) {
                    //showCzbLowBattery();
                    return ;
                }
                this._sendDataToWXDevice("A2", function (data) {
                    delog("开始读卡!!!!");
                    //readCard();
                });
            });
        });
    },

    _sendDataToWXDevice : function(content, func) {
        //var sendDatas = this._convertToBluetoothProtocol(content);
        var sendDatas = ["33800fc2010b008009010700a400000210017f"];
        this.bleInit_sendData(sendDatas, 0);
        var p = function() {
            var result = false;
            if ((parseInt(sendDatas[0].substr(2, 2), 16) == wxDeviceDataIndex) && isLastPackage) {
                delog("wxDeviceData=" + wxDeviceData);
                func(wxDeviceData);
                wxDeviceData = "";
                result =  true;
            }
            return result;
        }
        var time = 0;
        var tempTimers = function() {
            setTimeout(function() {
                if (p()) {
                } else {
                    if (time < 25) {
                        time++;
                        tempTimers();
                    } else {
                        delog("timeout,again please");
//                        sendDataToWXDeviceError();
                    }
                }
            }, 400);
        }
        tempTimers();

        return wxDeviceData;
    },

    _convertToBluetoothProtocol : function(str) {
        
        var maxDataCount = 95;
        var len = str.length / 2;
        var multi = len / maxDataCount;
        if (len % maxDataCount != 0) {
            multi++;
        }
        var pgkLen;
        var pgkIndex = 1;
        var ctl;
        var array = new Array();
        var count = Byte2Str16((sendCommandCount % 16));
        var strPgkIndex = 0;
        while (len > 0) {
            console.log("len=" + len + ",maxDataCount=" + maxDataCount);
            if (len > maxDataCount) {
                pgkLen = maxDataCount;
            } else {
                pgkLen = len;
            }
            if(pgkIndex == 1) {
                ctl = multi - pgkIndex & 127 | 128;
            } else {
                ctl = multi - pgkIndex & 127;
            }
            var s = count + Byte2Str16(ctl) + Byte2Str16(pgkLen) + str.substr(strPgkIndex, pgkLen * 2);

            s = "33" + addBcc(s);
            array.push(s);
            pgkIndex++;
            strPgkIndex += pgkLen * 2;
            len -= pgkLen;
        }
        sendCommandCount++;
        return array;
    },
}
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
/**
     * base64编码
     * @param {Object} str
     */
    function base64encode(str){
        var out, i, len;
        var c1, c2, c3;
        len = str.length;
        i = 0;
        out = "";
        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                out += base64EncodeChars.charAt(c1 >> 2);
                out += base64EncodeChars.charAt((c1 & 0x3) << 4);
                out += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                out += base64EncodeChars.charAt(c1 >> 2);
                out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
                out += base64EncodeChars.charAt((c2 & 0xF) << 2);
                out += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
            out += base64EncodeChars.charAt(c3 & 0x3F);
        }
        return out;
    }
    /**
     * base64解码
     * @param {Object} str
     */
    function base64decode(str){
        var c1, c2, c3, c4;
        var i, len, out;
        len = str.length;
        i = 0;
        out = "";
        while (i < len) {
            /* c1 */
            do {
                c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
            }
            while (i < len && c1 == -1);
            if (c1 == -1)
                break;
            /* c2 */
            do {
                c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
            }
            while (i < len && c2 == -1);
            if (c2 == -1)
                break;
            out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
            /* c3 */
            do {
                c3 = str.charCodeAt(i++) & 0xff;
                if (c3 == 61)
                    return out;
                c3 = base64DecodeChars[c3];
            }
            while (i < len && c3 == -1);
            if (c3 == -1)
                break;
            out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
            /* c4 */
            do {
                c4 = str.charCodeAt(i++) & 0xff;
                if (c4 == 61)
                    return out;
                c4 = base64DecodeChars[c4];
            }
            while (i < len && c4 == -1);
            if (c4 == -1)
                break;
            out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
        }
        return out;
    }
    /**
     * utf16转utf8
     * @param {Object} str
     */
    function utf16to8(str){
        var out, i, len, c;
        out = "";
        len = str.length;
        for (i = 0; i < len; i++) {
            c = str.charCodeAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                out += str.charAt(i);
            }
            else
            if (c > 0x07FF) {
                out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
                out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
                out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
            }
            else {
                out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
                out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
            }
        }
        return out;
    }
    /**
     * utf8转utf16
     * @param {Object} str
     */
    function utf8to16(str){
        var out, i, len, c;
        var char2, char3;
        out = "";
        len = str.length;
        i = 0;
        while (i < len) {
            c = str.charCodeAt(i++);
            switch (c >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    // 0xxxxxxx
                    out += str.charAt(i - 1);
                    break;
                case 12:
                case 13:
                    // 110x xxxx 10xx xxxx
                    char2 = str.charCodeAt(i++);
                    out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;
                case 14:
                    // 1110 xxxx10xx xxxx10xx xxxx
                    char2 = str.charCodeAt(i++);
                    char3 = str.charCodeAt(i++);
                    out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
                    break;
            }
        }
        return out;
    }
// 16进制的字符串转换byte数组
function Str162Bytes(str) {
    var pos = 0;
    var len = str.length;
    if (len % 2 != 0) {
        return null;
    }
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i < len; i++) {
        var s = str.substr(pos, 2);
        var v = parseInt(s, 16);
        hexA.push(v);
        pos += 2;
    }
    return hexA;
}

function Bytes2Str16(arr) {
    var str = "";
    for (var i = 0; i < arr.length; i++) {
        var tmp = arr[i].toString(16);
        if (tmp.length == 1) {
            tmp = "0" + tmp;
        }
        str += tmp;
    }
    return str;
}
function Byte2Str16(byte) {
    var str = "";
    var str = byte.toString(16);
    if (str.length == 1) {
        str = "0" + str;
    }
    return str;
}
// byte数组转换普通字符串
function bytes2Str10(array) {
    var result = "";
    for (var i = 0; i < array.length; i++) {
        result += String.fromCharCode(parseInt(array[i]));
    }
    return result;
}
// 普通字符串转换长byte数组
function Str102Bytes(str){
    var hexA = new Array();
    for(var i=0; i<str.length; i++){
        var s = str.charCodeAt(i);
        hexA.push(s);
    }
    return hexA;
}
function addBcc(str) {
    var byteArray = Str162Bytes(str);
    var len = byteArray.length;
    for (var i = 0; i < len; i++) {
        byteArray[len] ^= byteArray[i];
    }
    return Bytes2Str16(byteArray);
}